"""
加密解密工具类
"""

# 私钥,用于解密
import json
import logging
import math
import random
import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

private_key = '-----BEGIN PRIVATE KEY-----\n' + 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAITfvlC8+Nr+vz3DnhuCWW41ax8PG+rCiXt/f4XjRMlj9ZC2AuMMbtHLsTMLhCrhgHt1MxdcoYtqvQfxu4AVOh6pZrxMr2AiyNpw8SecmM3m0YWYNc7tnUB6/vlLyQduikD4qaxNiB5FcUiRpiRoLpz7rT6UV+/zDh+ibgvZRLDRAgMBAAECgYB7/mMV6tJ7YkBKPdK8Lw6PZq/5Att1XmZ3ZYo2Adg96tbMXN0izYZYprFMRhHnBhokm0C7K0jg1hFiaXUkWCqr83H+Y+DZ7js9NDhApPYAELQDIu288/nz34mjU/wnIGWP6WK5PCd1QjR8ltFay1TDLecdavHHjWGfHOMYnY5/dQJBAOZ4ICB+VrXMwR8KUR3r420YAHPwQDQKDetMHwgYHtFUH/k3CtKzPrltx103OhQcKyfrkoPj8SREZZISaBEQL6cCQQCTl+pjOSMud4hFTvfTnkGx9EZT3dBAv31ZfzHCu4g41FxRLyJLY6iKce069IhMjC2gfoLtwDLM/dKzRAuw9+rHAkAd9/zlfMg1t7xdFvBZXbUjGH3mlZUjrzMEJ8/ZM5m+SpwlwfyMTXaYkifcfTP2LXuHI2DX+an/t00l43LY1Sv9AkAEgQ5WGNhKArvV4aMOgjXfCGVdCdfhIfbhVFBgcPinQ1PN5nJVeqUaFH/43J2MOHrr+vBj8Qmb1+MmNV1l+SrhAkArJjCosjMI32RT3GmC6+gwxADR9Ib53yDHwRoMeO34dgK3hj3+e66Jhpcht3AjXBVs7bF9xzXcePpxxCka9cEv' + '\n-----END PRIVATE KEY-----'

# 公钥,用于加密
public_key = '-----BEGIN PUBLIC KEY-----\n' + 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfXfMzgg4m5RRLg2vcrYBFN4sBhE1VtW1sBkXxC5wtCRaOZv0kudk9CIQfU6c+eEaaZKUnygxHWdSqdwURCE0IKgLcolXF+RHmu/rl977FfjRg9pAkBg5z05PfHDqWqkIsqX0iRaSP31BUZOgtwafbiBv2dBvRBMdq03ty4q8OQQIDAQAB' + '\n-----END PUBLIC KEY-----'

# 基本字符表
base_str = 'abcdefghijklmnopqrstuvwxyz0123456789'
# rsa分块加密的数量
MAX_LENTH = 117

# AES加密的块
MAX_ENCODE_LENTH = 16

# rsa解密块的数值
MAX_DECODE_LENTH = 128


def random_key(len_key):
    """
    获取随机的key字符串
    :param len_key: 字符串长度
    :return:
    """
    r = ''
    r_len = len(base_str) - 1
    for i in range(len_key):
        r += base_str[random.randint(0, r_len)]
    return r


def decode_by_private(origin):
    """
    使用rsa 解密key数据
    :param origin: 原始数据
    :return:
    """
    cipher = PKCS1_cipher.new(RSA.importKey(private_key))
    origin_b = base64.b64decode(origin)
    origin_len = len(origin_b)
    if origin_len <= MAX_DECODE_LENTH:
        return cipher.decrypt(origin_b, 0).decode('utf-8')
    else:
        total_b = bytes()
        for i in range(math.ceil(origin_len / MAX_DECODE_LENTH)):
            if origin_len > (i + 1) * MAX_DECODE_LENTH:
                cut_b = origin_b[i * MAX_DECODE_LENTH:(i + 1) * MAX_DECODE_LENTH]
            else:
                cut_b = origin_b[i * MAX_DECODE_LENTH:]
            print(len(cut_b))
            total_b += (cipher.decrypt(cut_b, 0))
            print('total_len:', len(total_b))
            print(base64.b64encode(total_b).decode('utf-8'))
        return total_b.decode('utf-8')


def encrypt_key(key):
    """
    使用rsa加密key数据
    :param key: 原始数据
    :return:
    """
    cipher = PKCS1_cipher.new(RSA.importKey(public_key))
    key_b = key.encode('utf-8')
    key_len = len(key_b)
    if key_len <= MAX_LENTH:
        return base64.b64encode(cipher.encrypt(key_b)).decode('utf-8')
    else:
        total_b = bytes()
        for i in range(math.ceil(key_len / MAX_LENTH)):
            if key_len > (i + 1) * MAX_LENTH:
                total_b += (cipher.encrypt(key_b[i * MAX_LENTH:(i + 1) * MAX_LENTH]))
            else:
                total_b += (cipher.encrypt(key_b[i * MAX_LENTH:]))
        return base64.b64encode(total_b).decode('utf-8')


def pad(data, block_size):
    """
        对数据添加边界
    :param data: 原始数据的bytes
    :param block_size: 块儿的大小,前后端要一致
    :return:
    """
    padding_size = block_size - len(data) % block_size
    return data + bytes([padding_size] * padding_size)


def encrypt_content(data, key):
    """
    使用key对原始数据进行AES加密
    :param data: 原始数据
    :param key: 加密的key值
    :return:
    """
    data = json.dumps(data)
    data_bytes = data.encode('utf-8')
    aes = AES.new(key.encode('utf-8'), AES.MODE_ECB)
    t = aes.encrypt(pad(data_bytes, MAX_ENCODE_LENTH))
    print('aes:', type(t))

    return base64.b64encode(t).decode('utf-8')


def decode_aes(data, key):
    """
    使用key对加密数据进行解密
    :param data: 加密数据
    :param key: 解密key值
    :return:
    """
    data_bytes = base64.b64decode(data)
    aes = AES.new(key.encode('utf-8'), AES.MODE_ECB)
    t = aes.decrypt(data_bytes)
    return unpad(t, AES.block_size).decode('utf-8')


def decode(res):
    """
    对后台返回的数据进行解密
    :param res:
    :return:
    """
    try:
        if 'encrypted' not in res or 'requestData' not in res:
            return res
        res = json.loads(res)
        key_res = res['encrypted']
        data_res = res['requestData']
        key_decode = decode_by_private(key_res)
        data_decode = decode_aes(data_res, key_decode)
        return data_decode
    except Exception as e:
        logging.getLogger('main').error('解密失败:{}'.format(e))
        return res


def encode_data(data):
    """
    对原始数据进行rsa,AES混合加密,首先获取随机16位key值,对key进行ras加密,
    使用该key值对原始数据进行AES加密
    :param data: 原始数据
    :return:
    """
    key = random_key(16)
    key_encode = encrypt_key(key)
    content_encode = encrypt_content(data, key)
    return {'encrypted': key_encode, 'requestData': content_encode}
